#include <iostream>
#include <vector>
#include <string>
#include <iomanip>
#include <algorithm>
#include <map>
#include <ctime>
#include <sstream>
#include <limits>
//�����ռ�
using namespace std;

// �˵���¼�ṹ��
struct Record {
    string date;// ���ڣ���ʽΪYYYY-MM-DD
    double amount;// ��֧��С����ʾ
    string category;// ������ڷ���ͳ��
    string note;// ��ע����¼������Ϣ
    bool isIncome; // trueΪ���룬falseΪ֧��
};

// Ԥ��ṹ��
struct Budget {
    double limit;
    double used;
};

// ȫ�ֱ���
vector<Record> records;
Budget monthlyBudget = {0.0, 0.0};
string currentYearMonth; // ��ǰ���£���ʽΪYYYY-MM

// ��������
void displayMainMenu();
void addIncome();
void addExpense();
void showAllRecords();//�ָ�����
void queryRecords();
void setBudget();
void showMonthlyReport();
bool isValidDate(const string& date);
bool isValidAmount(double amount);
string getCurrentYearMonth();
void pressAnyKeyToContinue();
void clearScreen();

int main() {
	currentYearMonth = getCurrentYearMonth();
    // test
    // test2

    while (true) {
        clearScreen();
        displayMainMenu();

        int choice;
        cout << "������ѡ����ţ�";
        while (!(cin >> choice)) {
        // ���������Ч��������뻺��������ʾ�û���������
        cin.clear();  // ��������־
        cin.ignore(numeric_limits<streamsize>::max(), '\n');  // ������Ч������
        cout << "��Ч���룬������һ����Ч��������ţ�";
    	}
        // ������뻺����
        cin.ignore(numeric_limits<streamsize>::max(), '\n');

        switch (choice) {
            case 1:
                addIncome();
                break;
            case 2:
                addExpense();
                break;
            case 3:
                showAllRecords();
                break;
            case 4:
                queryRecords();
                break;
            case 5:
                setBudget();
                break;
            case 6:
                showMonthlyReport();
                break;
            case 7:
                cout << "��лʹ�ø����˵�����ϵͳ���ټ���" << endl;
                return 0;
            default:
                cout << "��Ч��ѡ����������룡" << endl;
                pressAnyKeyToContinue();
        }
    }
    return 0;
}

// �˵���ʾ
void displayMainMenu() {
    cout << "=================================" << endl;
    cout << "��ӭʹ�ø����˵�����ϵͳ" << endl;
    cout << "=================================" << endl;
    cout << "��ѡ�������" << endl;
    cout << "1. ��¼����" << endl;
    cout << "2. ��¼֧��" << endl;
    cout << "3. �鿴�����˵�" << endl;
    cout << "4. ��ѯ�˵�" << endl;
    cout << "5. �����¶�Ԥ��" << endl;
    cout << "6. �鿴�¶�ͳ�Ʊ���" << endl;
    cout << "7. �˳�ϵͳ" << endl;
}

// ��¼���빦��
void addIncome() {
    clearScreen();
    cout << "=================================" << endl;
    cout << "��ӭʹ�ø����˵�����ϵͳ" << endl;
    cout << "=================================" << endl;
    cout << "������������Ϣ��" << endl;

    Record newRecord;
    newRecord.isIncome = true;

    // ��������
    while (true) {
        cout << "���ڣ�YYYY-MM-DD����";
        getline(cin, newRecord.date);
        if (isValidDate(newRecord.date)) {
            break;
        } else {
            cout << "���ڸ�ʽ��Ч�����������룡" << endl;
        }
    }

    // ������
    while (true) {
        cout << "��";
        cin >> newRecord.amount;
        if (isValidAmount(newRecord.amount) && newRecord.amount > 0) {
            break;
        } else {
            cout << "������Ϊ���������������룡" << endl;
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
        }
    }
    cin.ignore(); // ������з�

    // �������
    cout << "����繤�ʡ�����ȣ���";
    getline(cin, newRecord.category);

    // ���뱸ע
    cout << "��ע��";
    getline(cin, newRecord.note);

    // ���ӵ���¼�б�
    records.push_back(newRecord);
    cout << "�����ѳɹ���¼��" << endl;

    pressAnyKeyToContinue();
}

// ��¼֧������
void addExpense() {
    clearScreen();
    cout << "=================================" << endl;
    cout << "��ӭʹ�ø����˵�����ϵͳ" << endl;
    cout << "=================================" << endl;
    cout << "������֧����Ϣ��" << endl;

    Record newRecord;
    newRecord.isIncome = false;

    // ��������
    while (true) {
        cout << "���ڣ�YYYY-MM-DD����";
        getline(cin, newRecord.date);
        if (isValidDate(newRecord.date)) {
            break;
        } else {
            cout << "���ڸ�ʽ��Ч�����������룡" << endl;
        }
    }

    // ������
    while (true) {
        cout << "��";
        cin >> newRecord.amount;
        if (isValidAmount(newRecord.amount) && newRecord.amount > 0) {
            break;
        } else {
            cout << "������Ϊ���������������룡" << endl;
            cin.clear();
            cin.ignore(numeric_limits<streamsize>::max(), '\n');
        }
    }
    cin.ignore(); // ������з�

    // �������
    cout << "������������ͨ������ȣ���";
    getline(cin, newRecord.category);

    // ���뱸ע
    cout << "��ע��";
    getline(cin, newRecord.note);

    // ���ӵ���¼�б�
    records.push_back(newRecord);

    // ��������Ԥ��
    string recordMonth = newRecord.date.substr(0, 7); // ��ȡ���²���
    if (recordMonth == currentYearMonth) {
        monthlyBudget.used += newRecord.amount;
    }

    cout << "֧���ѳɹ���¼��" << endl;

    pressAnyKeyToContinue();
}

// �鿴�����˵�����
void showAllRecords() {
    clearScreen();
    cout << "=================================" << endl;
    cout << "�����˵���¼" << endl;
    cout << "=================================" << endl;

    if (records.empty()) {
        cout << "�����˵���¼��" << endl;
        pressAnyKeyToContinue();
        return;
    }

    // ��ʾ�����¼
    cout << "�����¼��" << endl;
    cout << setw(12) << "����" << setw(10) << "���" << setw(15) << "���" << setw(20) << "��ע" << endl;
    cout << "--------------------------------------------------" << endl;

    bool hasIncome = false;
    for (const auto& record : records) {
        if (record.isIncome) {
            hasIncome = true;
            cout << setw(12) << record.date
                 << setw(10) << fixed << setprecision(2) << record.amount
                 << setw(15) << record.category
                 << setw(20) << record.note << endl;
        }
    }
    if (!hasIncome) cout << "���������¼" << endl;

    // ��ʾ֧����¼
    cout << "\n֧����¼��" << endl;
    cout << setw(12) << "����" << setw(10) << "���" << setw(15) << "���" << setw(20) << "��ע" << endl;
    cout << "--------------------------------------------------" << endl;

    bool hasExpense = false;
    for (const auto& record : records) {
        if (!record.isIncome) {
            hasExpense = true;
            cout << setw(12) << record.date
                 << setw(10) << fixed << setprecision(2) << record.amount
                 << setw(15) << record.category
                 << setw(20) << record.note << endl;
        }
    }
    if (!hasExpense) cout << "����֧����¼" << endl;

    pressAnyKeyToContinue();
}

// ��ѯ�˵�����
void queryRecords() {
    clearScreen();
    cout << "=================================" << endl;
    cout << "�˵���ѯ" << endl;
    cout << "=================================" << endl;
    cout << "��ѡ���ѯ��ʽ��" << endl;
    cout << "1. �����ڲ�ѯ" << endl;
    cout << "2. �����ڷ�Χ��ѯ" << endl;
    cout << "3. ������ѯ" << endl;
    cout << "4. �������˵�" << endl;
    cout << "������ѡ����ţ�";

    int choice;
    while (!(cin >> choice)) {
        // ���������Ч��������뻺��������ʾ�û���������
        cin.clear();  // ��������־
        cin.ignore(numeric_limits<streamsize>::max(), '\n');  // ������Ч������
        cout << "��Ч���룬������һ����Ч��������ţ�";
    }
    cin.ignore(); // ������з�

    vector<Record> result;

    switch (choice) {
        case 1: {  // �����ڲ�ѯ
            string date;
            while (true) {
                cout << "�������ѯ���ڣ�YYYY-MM-DD����";
                getline(cin, date);
                if (isValidDate(date)) {
                    break;
                } else {
                    cout << "���ڸ�ʽ��Ч�����������룡" << endl;
                }
            }

            // ����ƥ��ļ�¼
            for (const auto& record : records) {
                if (record.date == date) {
                    result.push_back(record);
                }
            }
            break;
        }
        case 2: {  // �����ڷ�Χ��ѯ
            string startDate, endDate;
            while (true) {
                cout << "�����뿪ʼ���ڣ�YYYY-MM-DD����";
                getline(cin, startDate);
                if (isValidDate(startDate)) {
                    break;
                } else {
                    cout << "���ڸ�ʽ��Ч�����������룡" << endl;
                }
            }

            while (true) {
                cout << "������������ڣ�YYYY-MM-DD����";
                getline(cin, endDate);
                if (isValidDate(endDate)) {
                    break;
                } else {
                    cout << "���ڸ�ʽ��Ч�����������룡" << endl;
                }
            }

            // ����ƥ��ļ�¼
            for (const auto& record : records) {
                if (record.date >= startDate && record.date <= endDate) {
                    result.push_back(record);
                }
            }
            break;
        }
        case 3: {  // ������ѯ
            string category;
            cout << "�������ѯ���";
            getline(cin, category);

            // ����ƥ��ļ�¼
            for (const auto& record : records) {
                if (record.category == category) {
                    result.push_back(record);
                }
            }
            break;
        }
        case 4:
            return;
        default:
            cout << "��Чѡ�" << endl;
            pressAnyKeyToContinue();
            return;
    }

    // ��ʾ��ѯ���
    clearScreen();
    cout << "=================================" << endl;
    cout << "��ѯ���" << endl;
    cout << "=================================" << endl;

    if (result.empty()) {
        cout << "û���ҵ�ƥ��ļ�¼��" << endl;
        pressAnyKeyToContinue();
        return;
    }

    // ��ʾ�����¼
    cout << "�����¼��" << endl;
    cout << setw(12) << "����" << setw(10) << "���" << setw(15) << "���" << setw(20) << "��ע" << endl;
    cout << "--------------------------------------------------" << endl;

    bool hasIncome = false;
    for (const auto& record : result) {
        if (record.isIncome) {
            hasIncome = true;
            cout << setw(12) << record.date
                 << setw(10) << fixed << setprecision(2) << record.amount
                 << setw(15) << record.category
                 << setw(20) << record.note << endl;
        }
    }
    if (!hasIncome) {
        cout << "�������¼" << endl;
    }

    cout << endl;

    // ��ʾ֧����¼
    cout << "֧����¼��" << endl;
    cout << setw(12) << "����" << setw(10) << "���" << setw(15) << "���" << setw(20) << "��ע" << endl;
    cout << "--------------------------------------------------" << endl;

    bool hasExpense = false;
    for (const auto& record : result) {
        if (!record.isIncome) {
            hasExpense = true;
            cout << setw(12) << record.date
                 << setw(10) << fixed << setprecision(2) << record.amount
                 << setw(15) << record.category
                 << setw(20) << record.note << endl;
        }
    }
    if (!hasExpense) {
        cout << "��֧����¼" << endl;
    }

    pressAnyKeyToContinue();
}

//�����¶�Ԥ��
void setBudget() {
    clearScreen();
    cout << "=================================" << endl;
    cout << "�����¶�Ԥ��" << endl;
    cout << "=================================" << endl;

    cout << "��ǰ�¶�Ԥ�㣺" << monthlyBudget.limit << " Ԫ" << endl;
    cout << "��ǰ����Ԥ�㣺" << monthlyBudget.used << " Ԫ" << endl;
    cout << "ʣ�����Ԥ�㣺" << (monthlyBudget.limit - monthlyBudget.used) << " Ԫ" << endl;

    cout << "�������µ��¶�Ԥ�㣨����0����ȡ������";
    double newBudget;
    cin >> newBudget;

    if (newBudget > 0) {
        monthlyBudget.limit = newBudget;
        monthlyBudget.used = 0.0;

        // ���¼��㵱ǰ�·ݵ�����Ԥ��
        for (const auto& record : records) {
            string recordMonth = record.date.substr(0, 7);
            if (!record.isIncome && recordMonth == currentYearMonth) {
                monthlyBudget.used += record.amount;
            }
        }

        cout << "�¶�Ԥ���Ѹ���Ϊ��" << monthlyBudget.limit << " Ԫ" << endl;
    } else {
        cout << "ȡ�������¶�Ԥ��" << endl;
    }

    pressAnyKeyToContinue();
}

//�鿴�¶�ͳ�Ʊ���
void showMonthlyReport() {
    clearScreen();
    cout << "=================================" << endl;
    cout << "�¶�ͳ�Ʊ���" << endl;
    cout << "=================================" << endl;

    string month;
    cout << "������Ҫͳ�Ƶ����£�YYYY-MM����������ͳ�Ƶ�ǰ�·ݣ�";
    getline(cin, month);

    if (month.empty()) {
        month = currentYearMonth;
    } else if (!isValidDate(month + "-01")) { // ������¸�ʽ�Ƿ���Ч
        cout << "���¸�ʽ��Ч��" << endl;
        pressAnyKeyToContinue();
        return;
    }

    double totalIncome = 0.0;
    double totalExpense = 0.0;
    map<string, double> incomeCategories;
    map<string, double> expenseCategories;

    for (const auto& record : records) {
        string recordMonth = record.date.substr(0, 7);
        if (recordMonth == month) {
            if (record.isIncome) {
                totalIncome += record.amount;
                incomeCategories[record.category] += record.amount;
            } else {
                totalExpense += record.amount;
                expenseCategories[record.category] += record.amount;
            }
        }
    }

    cout << "ͳ���·ݣ�" << month << endl;
    cout << "�����룺" << totalIncome << " Ԫ" << endl;
    cout << "��֧����" << totalExpense << " Ԫ" << endl;
    cout << "�����룺" << (totalIncome - totalExpense) << " Ԫ" << endl;

    if (!incomeCategories.empty()) {
        cout << "\n�������ͳ�ƣ�" << endl;
        for (const auto& category : incomeCategories) {
            cout << setw(15) << category.first << ": " << category.second << " Ԫ" << endl;
        }
    }

    if (!expenseCategories.empty()) {
        cout << "\n֧�����ͳ�ƣ�" << endl;
        for (const auto& category : expenseCategories) {
            cout << setw(15) << category.first << ": " << category.second << " Ԫ" << endl;
        }
    }

    // ����ǵ�ǰ�·ݣ���ʾԤ����Ϣ
    if (month == currentYearMonth && monthlyBudget.limit > 0) {
        cout << "\nԤ����Ϣ��" << endl;
        cout << "Ԥ���޶" << monthlyBudget.limit << " Ԫ" << endl;
        cout << "����Ԥ�㣺" << monthlyBudget.used << " Ԫ" << endl;
        cout << "ʣ��Ԥ�㣺" << (monthlyBudget.limit - monthlyBudget.used) << " Ԫ" << endl;
        cout << "Ԥ��ʹ���ʣ�" << (monthlyBudget.used / monthlyBudget.limit * 100) << "%" << endl;
    }

    pressAnyKeyToContinue();
}

// ��������
bool isValidDate(const string& date) {
    if (date.length() != 10) return false;
    if (date[4] != '-' || date[7] != '-') return false;

    int year, month, day;
    try {
        year = stoi(date.substr(0, 4));
        month = stoi(date.substr(5, 2));
        day = stoi(date.substr(8, 2));
    } catch (...) {
        return false;
    }

    if (year < 1900 || year > 2100) return false;
    if (month < 1 || month > 12) return false;

    // �򵥵�������֤�����������꣩
    int daysInMonth[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
    if (day < 1 || day > daysInMonth[month-1]) {
        return false;
    }

    return true;
}

bool isValidAmount(double amount) {
    return !cin.fail();
}

string getCurrentYearMonth() {
    time_t now = time(0);
    tm *ltm = localtime(&now);

    ostringstream oss;
    oss << (1900 + ltm->tm_year) << "-"
        << setw(2) << setfill('0') << (1 + ltm->tm_mon);

    return oss.str();
}

void pressAnyKeyToContinue() {
    cout << "\n��������������˵�..";
    cin.get();
}

void clearScreen() {
    #ifdef _WIN32
        system("cls");
    #else
        system("clear");
    #endif
}
